using System;
using System.Xml;
using System.Drawing;
using System.Globalization;
using System.Windows.Forms;
using needle.UI.Controls.Flat.Resources;
using needle.UI.Controls.Flat.Utilities.Drawing;
using needle.UI.Controls.Flat.Resources.Keys;
using needle.UI.Controls.Flat.Windows.Forms.Helpers;

namespace needle.UI.Controls.Flat.Windows.Docking
{
    public class Content
    {
		#region PropChangeEventArgs

		public class PropChangeEventArgs : EventArgs
		{
			private Content item = null;
			private string prop = String.Empty;
			private object oldValue = null;

			public PropChangeEventArgs(Content item, string prop, object oldValue)
			{
				this.item = item;
				this.prop = prop;
				this.oldValue = oldValue;
			}

			public Content Item
			{
				get {return this.item;}
			}

			public string PropertyName
			{
				get {return this.prop;}
			}
		
			public object OldValue
			{
				get {return this.oldValue;}
			}
		}

		#endregion

        protected static int mdefaultDisplaySize = 150;
        protected static int mdefaultAutoHideSize = 150;
        protected static int mdefaultFloatingSize = 150;
        protected static int mdefaultLocation = 150;
		protected static int mcounter = 0;

        protected Control mcontrol;
        protected string mtitle;
        protected string mfullTitle;
		protected Icon micon;
		protected ImageList mimageList;
        protected int mimageIndex;
		protected int morder;
		protected Size mdisplaySize;
        protected Size mautoHideSize;
        protected Size mfloatingSize;
		protected Point mdisplayLocation;
        protected DockingManager mmanager;
        protected bool mdocked;
        protected bool mautoHidden;
        protected bool mvisible;
        protected bool mcaptionBar;
        protected bool mcloseButton;
        protected bool mhideButton;
		protected bool mcloseOnHide;
		protected object mtag;
        protected AutoHidePanel mautoHidePanel;
        protected WindowContent mparentWindowContent;
		protected Restore mdefaultRestore;
		protected Restore mautoHideRestore;
		protected Restore mdockingRestore;
		protected Restore mfloatingRestore;

		public delegate void PropChangeEventHandler(object sender, PropChangeEventArgs e);
		
		public event PropChangeEventHandler PropertyChanging;
        public event PropChangeEventHandler PropertyChanged;

		#region Constructors

		public Content(XmlTextReader xmlIn, int formatVersion)
        {
            mcontrol = null;
            mtitle = "";
            mfullTitle = "";
            mimageList = null;
			micon = null;
            mimageIndex = -1;
            mmanager = null;
            mparentWindowContent = null;
            mdisplaySize = new Size(mdefaultDisplaySize, mdefaultDisplaySize);
            mautoHideSize = new Size(mdefaultAutoHideSize, mdefaultAutoHideSize);
            mfloatingSize = new Size(mdefaultFloatingSize, mdefaultFloatingSize);
            mdisplayLocation = new Point(mdefaultLocation, mdefaultLocation);
			morder = mcounter++;
			mtag = null;
			mvisible = false;
			mdefaultRestore = null;
			mautoHideRestore = null;
			mfloatingRestore = null;
			mdockingRestore = null;
			mautoHidePanel = null;
			mdocked = true;
			mcaptionBar = true;
			mcloseButton = true;
            mhideButton = true;
            mautoHidden = false;
			mcloseOnHide = false;

			LoadFromXml(xmlIn, formatVersion);
        }

        public Content(DockingManager manager)
        {
            InternalConstruct(manager, null, "", null, -1, null);
        }

        public Content(DockingManager manager, Control control)
        {
            InternalConstruct(manager, control, "", null, -1, null);
        }

        public Content(DockingManager manager, Control control, string title)
        {
            InternalConstruct(manager, control, title, null, -1, null);
        }

        public Content(DockingManager manager, Control control, string title, ImageList imageList, int imageIndex)
        {
            InternalConstruct(manager, control, title, imageList, imageIndex, null);
        }

		public Content(DockingManager manager, Control control, string title, Icon icon)
		{
			InternalConstruct(manager, control, title, null, -1, icon);
		}
		
		protected void InternalConstruct(DockingManager manager, 
                                         Control control, 
                                         string title, 
                                         ImageList imageList, 
                                         int imageIndex,
										 Icon icon)
        {
            if (manager == null)
                throw new ArgumentNullException("DockingManager");

            mcontrol = control;
            mtitle = title;
            mimageList = imageList;
            mimageIndex = imageIndex;
			micon = icon;
            mmanager = manager;
            mparentWindowContent = null;
            morder = mcounter++;
            mvisible = false;
            mdisplaySize = new Size(mdefaultDisplaySize, mdefaultDisplaySize);
            mautoHideSize = new Size(mdefaultAutoHideSize, mdefaultAutoHideSize);
            mfloatingSize = new Size(mdefaultFloatingSize, mdefaultFloatingSize);
            mdisplayLocation = new Point(mdefaultLocation, mdefaultLocation);
			mdefaultRestore = new RestoreContentState(State.DockLeft, this);
			mfloatingRestore = new RestoreContentState(State.Floating, this);
            mautoHideRestore = new RestoreAutoHideState(State.DockLeft, this);
            mdockingRestore = mdefaultRestore;
            mautoHidePanel = null;
			mtag = null;
			mdocked = true;
            mcaptionBar = true;
            mcloseButton = true;
            mhideButton = true;
            mautoHidden = false;
			mcloseOnHide = false;
            mfullTitle = title;
        }

		#endregion

		#region Virtuals

		public virtual void OnPropertyChanging(PropChangeEventArgs e)
		{
			if (PropertyChanging != null)
				PropertyChanging(this, e);
		}

		public virtual void OnPropertyChanged(PropChangeEventArgs e)
		{
			if (PropertyChanged != null)
				PropertyChanged(this, e);
		}


		#endregion

		#region Properties

		public DockingManager DockingManager
        {
            get { return mmanager; }
			set { mmanager = value; }
        }

        public Control Control
        {
            get { return mcontrol; }
			
            set 
            {
                if (mcontrol != value)
                {
                    OnPropertyChanging(new PropChangeEventArgs(this, "Control", null));
                    mcontrol = value;
                    OnPropertyChanged(new PropChangeEventArgs(this, "Control", null));
                }
            }
        }

        public string Title
        {
            get { return mtitle; }

            set 
            {
                if (mtitle != value)
                {
                    OnPropertyChanging(new PropChangeEventArgs(this, "Title", null));
                    mtitle = value;
                    OnPropertyChanged(new PropChangeEventArgs(this, "Title", null));
                }
            }
        }
        
        public string FullTitle
        {
            get { return mfullTitle; }
            
            set
            {
                if (mfullTitle != value)
                {
                    OnPropertyChanging(new PropChangeEventArgs(this, "FullTitle", null));
                    mfullTitle = value;
                    OnPropertyChanged(new PropChangeEventArgs(this, "FullTitle", null));
                }
            }
        }

        public ImageList ImageList
        {
            get { return mimageList; }

            set 
            {
                if(mimageList != value) 
                {
                    OnPropertyChanging(new PropChangeEventArgs(this, "ImageList", null));
                    mimageList = value; 
                    OnPropertyChanged(new PropChangeEventArgs(this, "ImageList", null));
                }
            }
        }

        public int ImageIndex
        {
            get { return mimageIndex; }

            set 
            {
                if (mimageIndex != value)
                {
                    OnPropertyChanging(new PropChangeEventArgs(this, "ImageIndex", null));
                    mimageIndex = value;
                    OnPropertyChanged(new PropChangeEventArgs(this, "ImageIndex", null));
                }
            }
        }

		public Icon Icon
		{
			get { return micon; }

			set 
			{
				if (micon != value)
				{
					OnPropertyChanging(new PropChangeEventArgs(this, "Icon", null));
					micon = value;
					OnPropertyChanged(new PropChangeEventArgs(this, "Icon", null));
				}
			}
		}
		
		public bool CaptionBar
        {
            get { return mcaptionBar; }
            
            set
            {
                if (mcaptionBar != value)
                {
                    OnPropertyChanging(new PropChangeEventArgs(this, "CaptionBar", null));
                    mcaptionBar = value;
                    OnPropertyChanged(new PropChangeEventArgs(this, "CaptionBar", null));
                }
            }
        }

        public bool CloseButton
        {
            get { return mcloseButton; }
            
            set
            {
                if (mcloseButton != value)
                {
                    OnPropertyChanging(new PropChangeEventArgs(this, "CloseButton", null));
                    mcloseButton = value;
                    OnPropertyChanged(new PropChangeEventArgs(this, "CloseButton", null));
                }
            }
        }

        public bool HideButton
        {
            get { return mhideButton; }
            
            set
            {
                if (mhideButton != value)
                {
                    OnPropertyChanging(new PropChangeEventArgs(this, "HideButton", null));
                    mhideButton = value;
                    OnPropertyChanged(new PropChangeEventArgs(this, "HideButton", null));
                }
            }
        }

        public Size DisplaySize
        {
            get { return mdisplaySize; }

            set 
            {
                if (mdisplaySize != value)
                {
                    OnPropertyChanging(new PropChangeEventArgs(this, "DisplaySize", null));
                    mdisplaySize = value;
                    OnPropertyChanged(new PropChangeEventArgs(this, "DisplaySize", null));
                }
            }
        }
        
        public Size AutoHideSize
        {
            get { return mautoHideSize; }
            
            set
            {
                if (mautoHideSize != value)
                {
                    OnPropertyChanging(new PropChangeEventArgs(this, "AutoHideSize", null));
                    mautoHideSize = value;
                    OnPropertyChanged(new PropChangeEventArgs(this, "AutoHideSize", null));
                }
            }
        }

        public Size FloatingSize
        {
            get { return mfloatingSize; }

            set 
            {
                if (mfloatingSize != value)
                {
                    OnPropertyChanging(new PropChangeEventArgs(this, "FloatingSize", null));
                    mfloatingSize = value;
                    OnPropertyChanged(new PropChangeEventArgs(this, "FloatingSize", null));
                }
            }
        }

        public Point DisplayLocation
        {
            get { return mdisplayLocation; }

            set 
            {
                if (mdisplayLocation != value)
                {
                    OnPropertyChanging(new PropChangeEventArgs(this, "DisplayLocation", null));
                    mdisplayLocation = value;
                    OnPropertyChanged(new PropChangeEventArgs(this, "DisplayLocation", null));
                }
            }
        }
        
		public int Order
		{
			get { return morder; }
		}

		public bool CloseOnHide
		{
			get { return mcloseOnHide; }
			set { mcloseOnHide = value; }
		}

		public object Tag
		{
			get { return mtag; }
			set { mtag = value; }
		}

		public bool Visible
		{
			get { return mvisible; }
		}

		public Restore DefaultRestore
		{
			get { return mdefaultRestore; }
			set { mdefaultRestore = value; }
		}

        public Restore AutoHideRestore
        {
            get { return mautoHideRestore; }
            set { mautoHideRestore = value; }
        }
        
        public Restore DockingRestore
		{
			get { return mdockingRestore; }
			set { mdockingRestore = value; }
		}

		public Restore FloatingRestore
		{
			get { return mfloatingRestore; }
			set { mfloatingRestore = value; }
		}

        public bool Docked
        {
            get { return mdocked; }
			set { mdocked = value; }
        }

        public WindowContent ParentWindowContent
        {
            get { return mparentWindowContent; }
            
			set 
			{ 
				if (mparentWindowContent != value)
				{
					mparentWindowContent = value; 

                    UpdateVisibility();
				}
			}
        }

        public AutoHidePanel AutoHidePanel
        {
            get { return mautoHidePanel; }
            
            set 
            {
                if (mautoHidePanel != value)
                {
                    mautoHidePanel = value; 
                
                    UpdateVisibility();
				}
            }
        }

        internal bool AutoHidden
        {
            get { return mautoHidden; }

            set 
            { 
                if (mautoHidden != value)
                {
                    mautoHidden = value; 

                    UpdateVisibility();
				}                
            }
        }

		#endregion

		#region Methods

        public void UpdateVisibility()
        {
            mvisible = ((mparentWindowContent != null) || (mautoHidden && (mautoHidePanel != null)));
        }

		public void BringToFront()
		{
		    if (!mvisible)
		    {
			    mmanager.ShowContent(this);
            }
            
            if (mautoHidden)
            {
                mmanager.BringAutoHideIntoView(this);
            }
            else
            {
			    mparentWindowContent.BringContentToFront(this);
	        }
		}

		public Restore RecordRestore()
		{
			if (mparentWindowContent != null)
			{
			    if (mautoHidden)
                    return RecordAutoHideRestore();
                else
                {			    
				    Form parentForm = mparentWindowContent.ParentZone.FindForm();

				    if (parentForm != null)
				    {
					    if (parentForm is FloatingForm)
						    return RecordFloatingRestore();
					    else
						    return RecordDockingRestore();
				    }	
		        }
			}

			return null;
		}

        public Restore RecordAutoHideRestore()
        {
            mautoHideRestore = null;
                
            if (mparentWindowContent != null)
            {
                if (mautoHidden)
                {
                    AutoHidePanel ahp = mparentWindowContent.DockingManager.AutoHidePanelForContent(this);
                    
                    mautoHideRestore = ahp.RestoreObjectForContent(this);
                }
            }
        
            return mautoHideRestore;
        }

		public Restore RecordDockingRestore()
		{
			mdockingRestore = null;

			if (mparentWindowContent != null)
			{
				mdockingRestore = mparentWindowContent.RecordRestore(this);
			}

			if (mdockingRestore == null)
				mdockingRestore = mdefaultRestore;

			return mdockingRestore;
		}
		
		public Restore RecordFloatingRestore()
		{
			mfloatingRestore = null;

			if (mparentWindowContent != null)
			{
				mfloatingRestore = mparentWindowContent.RecordRestore(this);
			}
			if (mfloatingRestore == null)
				mfloatingRestore = mdefaultRestore;

			return mfloatingRestore;
		}

		internal void ContentBecomesFloating()
		{
			mdocked = false;

			if (mparentWindowContent != null)
			{
				switch(mparentWindowContent.State)
				{
					case State.DockLeft:
					case State.DockRight:
					case State.DockTop:
					case State.DockBottom:
						RecordDockingRestore();
						break;
					case State.Floating:
					default:
						break;
				}
			}
		}

        internal void ContentLeavesFloating()
        {
			mdocked = true;

            if (mparentWindowContent != null)
            {
                switch(mparentWindowContent.State)
                {
                    case State.DockLeft:
                    case State.DockRight:
                    case State.DockTop:
                    case State.DockBottom:
                        break;
                    case State.Floating:
                    default:
                        RecordFloatingRestore();
                        break;
                }
            }
        }

		internal void ReconnectRestore()
		{
			mdefaultRestore.Reconnect(mmanager);
			mautoHideRestore.Reconnect(mmanager);
			mdockingRestore.Reconnect(mmanager);
			mfloatingRestore.Reconnect(mmanager);
		}

		internal void SaveToXml(XmlTextWriter xmlOut)
		{
			xmlOut.WriteStartElement("Content");
			xmlOut.WriteAttributeString("Name", mtitle);
			xmlOut.WriteAttributeString("Visible", mvisible.ToString(CultureInfo.CurrentCulture));
            xmlOut.WriteAttributeString("Docked", mdocked.ToString(CultureInfo.CurrentCulture));
            xmlOut.WriteAttributeString("AutoHidden", mautoHidden.ToString(CultureInfo.CurrentCulture));
            xmlOut.WriteAttributeString("CaptionBar", mcaptionBar.ToString(CultureInfo.CurrentCulture));
            xmlOut.WriteAttributeString("CloseButton", mcloseButton.ToString(CultureInfo.CurrentCulture));
            xmlOut.WriteAttributeString("DisplaySize", DrawHelpers.SizeToString(mdisplaySize));
			xmlOut.WriteAttributeString("DisplayLocation", DrawHelpers.PointToString(mdisplayLocation));
            xmlOut.WriteAttributeString("AutoHideSize", DrawHelpers.SizeToString(mautoHideSize));
            xmlOut.WriteAttributeString("FloatingSize", DrawHelpers.SizeToString(mfloatingSize));
            xmlOut.WriteAttributeString("FullTitle", mfullTitle);

			xmlOut.WriteStartElement("DefaultRestore");
			mdefaultRestore.SaveToXml(xmlOut);
			xmlOut.WriteEndElement();

            xmlOut.WriteStartElement("AutoHideRestore");
            mautoHideRestore.SaveToXml(xmlOut);
            xmlOut.WriteEndElement();
            
			xmlOut.WriteStartElement("DockingRestore");
			mdockingRestore.SaveToXml(xmlOut);
			xmlOut.WriteEndElement();

			xmlOut.WriteStartElement("FloatingRestore");
			mfloatingRestore.SaveToXml(xmlOut);
			xmlOut.WriteEndElement();

			xmlOut.WriteEndElement();
		}

		internal void LoadFromXml(XmlTextReader xmlIn, int formatVersion)
		{
			string attrTitle = xmlIn.GetAttribute(0);
			string attrVisible = xmlIn.GetAttribute(1);
            string attrDocked = xmlIn.GetAttribute(2);
            string attrAutoHide = xmlIn.GetAttribute(3);
            string attrCaptionBar = xmlIn.GetAttribute(4);
            string attrCloseButton = xmlIn.GetAttribute(5);
            string attrDisplaySize = xmlIn.GetAttribute(6);
			string attrDisplayLocation = xmlIn.GetAttribute(7);
            string attrAutoHideSize = xmlIn.GetAttribute(8);
            string attrFloatingSize = xmlIn.GetAttribute(9);
            string attrFullTitle = attrTitle;
            
            if (formatVersion >= 5)
                attrFullTitle = xmlIn.GetAttribute(10);

			mtitle = attrTitle;
			mvisible = Convert.ToBoolean(attrVisible, CultureInfo.CurrentCulture);
            mdocked = Convert.ToBoolean(attrDocked, CultureInfo.CurrentCulture);
            mautoHidden = Convert.ToBoolean(attrAutoHide, CultureInfo.CurrentCulture);
            mcaptionBar = Convert.ToBoolean(attrCaptionBar, CultureInfo.CurrentCulture);
            mcloseButton = Convert.ToBoolean(attrCloseButton, CultureInfo.CurrentCulture);
            mdisplaySize = DrawHelpers.StringToSize(attrDisplaySize);
            mdisplayLocation = DrawHelpers.StringToPoint(attrDisplayLocation);
            mautoHideSize = DrawHelpers.StringToSize(attrAutoHideSize);
            mfloatingSize = DrawHelpers.StringToSize(attrFloatingSize);
            mfullTitle = attrFullTitle;

			mdefaultRestore = Restore.CreateFromXml(xmlIn, true, formatVersion);
			mautoHideRestore  = Restore.CreateFromXml(xmlIn, true, formatVersion);
            mdockingRestore  = Restore.CreateFromXml(xmlIn, true, formatVersion);
            mfloatingRestore = Restore.CreateFromXml(xmlIn, true, formatVersion);

			if (!xmlIn.Read())
				throw new ArgumentException(ResourceLibrary.GetString(WindowsControlsResourceKeys.InaccessibleNode,WindowsControlsResourceKeys.Root));
		
			if (xmlIn.NodeType != XmlNodeType.EndElement)
				throw new ArgumentException(ResourceLibrary.GetString(WindowsControlsResourceKeys.FinalElementNotFound,WindowsControlsResourceKeys.Root));
		}
    } 

	#endregion
}
